package com.dreamlike.demo.HttpUtil.Core.Generator;

import com.dreamlike.demo.HttpUtil.Annotation.Core.Request;
import com.dreamlike.demo.HttpUtil.Core.HttpDefinition;
import com.dreamlike.demo.HttpUtil.Core.Validator.HttpDefinitionValidateResult;
import com.dreamlike.demo.HttpUtil.Core.Validator.HttpDefinitionValidatorChain;
import com.dreamlike.demo.HttpUtil.Core.Validator.impl.AsyncValidator;
import com.dreamlike.demo.HttpUtil.Core.Validator.impl.EncodedInstanceValidator;
import com.dreamlike.demo.HttpUtil.Core.Validator.impl.ReturnSingleGenericValidator;
import com.dreamlike.demo.HttpUtil.Exception.IllegalHttpDefinitionException;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;

public class HttpDefinitionGenerator {
    private HttpDefinitionValidatorChain httpDefinitionValidatorChain;
    public static final String DEFAULT_EXECUTOR_NAME = "ForkJoin";
    private Executor defaultExecutor = ForkJoinPool.commonPool();
    private Map<String,Executor> executorMap;

    public HttpDefinitionGenerator(Map<String, Executor> executorMap,HttpDefinitionValidatorChain httpDefinitionValidatorChain) {
        this.executorMap = executorMap;
        this.httpDefinitionValidatorChain = httpDefinitionValidatorChain;
        executorMap.put(DEFAULT_EXECUTOR_NAME,defaultExecutor);
    }

    public HttpDefinitionGenerator(){
        this(new HashMap<>(),new HttpDefinitionValidatorChain(new AsyncValidator(),new ReturnSingleGenericValidator(),new EncodedInstanceValidator()));
    }

    public void addNewExecutor(Map<String,Executor> executorMap){
        this.executorMap.putAll(executorMap);
    }

    public HttpDefinition generate(Method method){
        String executorName = method.getAnnotation(Request.class).executorName();
        Executor executor = Optional.ofNullable(executorMap.get(executorName))
                .orElse(defaultExecutor);
        HttpDefinition httpDefinition = new HttpDefinition(method, executor);
        HttpDefinitionValidateResult result = httpDefinitionValidatorChain.validate(httpDefinition, false);
        if (result.hasError()){
            String formation = "不通过%s验证器，原因是%s:";
            String message = result.getErrorInfo()
                    .entrySet()
                    .stream()
                    .map(e -> String.format(formation, e.getKey().name(), e.getValue()))
                    .collect(Collectors.joining("\n"));
            throw new IllegalHttpDefinitionException(message);
        }
        return httpDefinition;
    }

}
